#pragma once
#include "ProgramState.h"
#include "../engine/singleton.h"
#include "../shared/shared_types.h"
#include "../phy/phycccp.h"
#include "../ai/AIManager.h"
#include "../engine/Map.h"
#include "../net/NetworkPackets.h"
#include <vector>
#include <queue>

namespace Putin{

// Handy Forward declarations
class GameObject;
class Unit;
class Bullet;
class Gamestate;
class RenderableUnit;
class NetworkClient;
class BattleControl;
class WorldLink;

#define KEYFRAME_INTERVAL 10

typedef std::map<int,Bullet*> BulletMap;

class UpdateEvent
{
public:
	virtual void frameEvent(BattleControl* bc ) = 0;
};

/**
 * The main in-game Program.
 * This is responsible for the main game loop
 * when controlling the units and playing the game
 */
class BattleControl : public ProgramState, public Singleton<BattleControl>
{
public:
	BattleControl(void);
	virtual ~BattleControl(void);
	
	friend class UpdateEvent;
	
	virtual bool quit();

protected:

	bool	mPaused;

	// Internals
	virtual bool	renderGraphics();
	virtual bool	renderOverlay();

protected:

	// Inherieted from ProgramState
public:
	/**
	 * Initialize subsystems
	 */
	virtual bool initialize();

	virtual void terminate();
	
	/**
	 * Frame update
	 */
	virtual bool update();
	
	/**
	 * Perform render routines
	 */ 
	virtual bool render();
	
	/**
	 * Load resources such as sounds and textures
	 */
	virtual bool loadResources();
	virtual bool loadMap(std::string filename);

	Gamestate* getState();


protected:

	// --- Key handling ---

	virtual void mouseUp(int x, int y, int mb);
	virtual void mouseMove(int x, int y);
	virtual void keyDown(char key);
	virtual void keyUp(char key);
	virtual void keyPress(char c);
	virtual void mouseDown(int x, int y, int mb);	

	// specific in game event handlers
	virtual void unitClicked(int unitID, Vec3f& pos, int mouse );
	virtual void groundClicked(Vec3f& pos, int mouse);

	virtual void executeCommand(NetworkCommand* nc);
	virtual void executeText(NetworkText* nt);

public:

	virtual bool spawnStatic(StaticObject* obj);
	virtual void removeStatic(int id);
	virtual bool spawnUnit(Unit* unit);
	virtual void spawnBullet(Bullet* b);
	virtual void removeBullet(Bullet* b);
	virtual Bullet* getBullet(int id);
	virtual void removeUnit(int id);
	bool	isMultiplay(){return mNetworkMode;}
	PhysicsHandler* getPhycccp(){return mPhycccp;}
	virtual BulletMap& getBullets(){return mBullets;}

	UpdateEvent*	mUpdateEvent;

protected:

	// Internal Helper functions.
	RenderableUnit* createRenderable(GameObject* go);
	void	removeRenderable(int id);
	Vec2f normalizeScreenCoord(Vec2f c);

	// Game data
	Gamestate* mGame;							// the game state
	std::vector<RenderableUnit*> mRenderables;	// renderables to connect to the RenderEngine
	std::map<int,StaticObject*> mStatics;		// static objects (stones etc).
	Map* mMap;	/*! The Map associated with this instance  */
	
	BulletMap	mBullets;
	// Sub systems
	PhysicsHandler* mPhycccp;
	AIManager*		mAIManager;
	NetworkClient*	mNet;

	// network stuff
	__int64			mFrameCounter;
	unsigned short	mFrameCounter16; // 16 bit frame counter
	bool			mNetworkMode;
	bool			mWaitForSync;

	
	
	//CommandQueue	mPendingCommands; // defined in NetworkClient
	//TextQueue		mPendingTexts;
	
	// Physic Init stuff
	std::queue<Unit*> mNotInitedUnits;
	std::queue<StaticObject*> mNotInitedStatics;


	WorldLink*	mWorldLink;
};

} // End namespace Putin